// 类—类型接口

/*******************  类实现接口 ******************/
// 一个接口可以约束类成员可以有哪些属性以及它们的类型

interface Human {
  // new (name: string): void; // 那么会提示我们这个类错误的实现了这个`Human`接口
  name: string; // name 属性
  eat(): void; // eat 方法
}

// implements 关键字实现接口
// 那么这里呢我们需要注意：类实现接口的时候必须实现接口中声明的所有属性
// 那么第二点呢：类只能约束接口的公有成员
// 那么接口呢也不能约束类的构造函数
class Asian implements Human {
  constructor(name: string) {
    this.name = name;
  }
  name: string;
  // private name: string; // 比如我们把 name 声明为一个私有成员这样会提示是不可以的`属性“name”在类型“Asian”中是私有属性，但在类型“Human”中不是。`
  eat() {}
  // 如果类定义一个自己的属性这样是可以的
  sleep() {}
}

/*******************  接口继承接口 ******************/

// 接口呢可以像类一样相互继承，并且一个接口可以继承多个接口
interface Man extends Human {
  run(): void;
}

interface Child {
  cry(): void;
}

// 同时继承 Man和Child
interface Boy extends Man, Child {}

// 定义一个对象，这个对象要符合Boy接口的定义
// 这里会提示我们 boy 需要包含四个属性，这四个属性呢分别来至 Human、Man和Child
// 从接口的继承呢可以看出，接口的继承可以抽离出可重用的接口也可以将多个接口合并成一个接口
let boy: Boy = {
  name: "",
  eat() {},
  run() {},
  cry() {},
};

/*******************  接口继承类 ******************/

// 接口继承类

// 接口除了可以继承接口之外，还可以继承类这就相当于接口把类的成员都抽象了出来，也就是只有类的成员结构而没有具体的实现

class Auto {
  state = 1;
  // private state3 = 3; // 如果类中有私有成员或者受保护成员，那么类“C”错误实现接口“AutoInterface”
  // protected state1 = 0;
}

// 用一个接口来继承 Auto 这个类
interface AutoInterface extends Auto{
  // 这个接口中就隐含了 state 属性
}

// 要想实现这个 AutoInterface 接口呢只要一个类的成员和 state 属性就可以了
class C implements AutoInterface{
  state: number = 1;
}

// 那么此外呢，Auto 的子类也可以实现 AutoInterface 这个接口
class Bus extends Auto implements AutoInterface{
  // 在这个子类中呢我们就不必要实现 state 属性了，因为它是 Auto 的子类自然就继承了 state 属性
  // 这里需要额外注意的是：接口在抽离类的成员的时候不仅抽离了公共成员而且抽离了私有成员和受保护成员
}
